/*
 * This file Copyright (c) 2015. Walle.
 * (http://www.wallellen.com). All rights reserved.
 *
 *
 * This file is dual-licensed under both the
 * Walle Agreement (WA) and the GNU General Public License.
 * You may elect to use one or the other of these licenses.
 *
 * This file is distributed in the hope that it will be
 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * Redistribution, except as permitted by whichever of the GPL
 * or WA you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or
 * modify this file under the terms of the GNU General
 * Public License, Version 3, as published by the Free Software
 * Foundation.  You should have received a copy of the GNU
 * General Public License, Version 3 along with this program;
 * if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 2. For the Walle Agreement (WA), this file
 * and the accompanying materials are made available under the
 * terms of the WA which accompanies this distribution, and
 * is available at http://www.wallellen.com/agreement.html
 *
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 */

package com.wallellen.authority.service.impl;

import com.wallellen.authority.dao.ActionDaoInter;
import com.wallellen.authority.dao.ActiontreeDaoInter;
import com.wallellen.authority.domain.Action;
import com.wallellen.authority.domain.Actiontree;
import com.wallellen.authority.domain.AuthKeyImpl;
import com.wallellen.authority.domain.AuthMenuImpl;
import com.wallellen.authority.service.ActionServiceInterface;
import com.wallellen.core.auth.domain.AuthKey;
import com.wallellen.core.auth.domain.LoginUser;
import com.wallellen.core.auth.domain.WebMenu;
import com.wallellen.core.sql.query.DBRule;
import com.wallellen.core.sql.query.DataQuery;
import com.wallellen.core.time.TimeTool;
import com.wallellen.web.easy.EasyUiTreeNode;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by walle on 12/12/15.
 */
@Service
public class ActionServiceImpl
        implements ActionServiceInterface {

    @Resource
    private ActionDaoInter actionDaoImpl;

    @Resource
    private ActiontreeDaoInter actiontreeDaoImpl;
    private Map<String, AuthKey> keyMap = new HashMap();

    @Transactional
    public Action insertActionEntity(Action entity, LoginUser user) {
        entity.setCuser(user.getId());
        entity.setCtime(TimeTool.getTimeDate14());
        entity.setMuser(user.getId());
        entity.setUtime(TimeTool.getTimeDate14());
        if (this.actionDaoImpl.getEntityByKey(entity.getAuthkey()) != null) {
            throw new RuntimeException("key已经存在!");
        }
        this.keyMap.clear();
        return this.actionDaoImpl.insertEntity(entity);
    }

    @Transactional
    public Action editActionEntity(Action entity, LoginUser user) {
        Action entity2 = this.actionDaoImpl.getEntity(entity.getId());
        entity2.setMuser(user.getId());
        entity2.setUtime(TimeTool.getTimeDate14());
        entity2.setLoginis(entity.getLoginis());
        entity2.setCheckis(entity.getCheckis());
        entity2.setState(entity.getState());
        entity2.setComments(entity.getComments());
        entity2.setName(entity.getName());
        entity2.setAuthkey(entity.getAuthkey());
        this.actionDaoImpl.editEntity(entity2);
        Action keyAction = this.actionDaoImpl.getEntityByKey(entity.getAuthkey());
        if ((keyAction != null) && (!keyAction.getId().equals(entity2.getId()))) {
            throw new RuntimeException("key已经存在!");
        }
        this.keyMap.clear();
        return entity2;
    }

    @Transactional
    public void deleteActionEntity(String id, LoginUser user) {
        this.actionDaoImpl.deleteEntity(this.actionDaoImpl.getEntity(id));
    }

    @Transactional
    public Action getActionEntity(String id) {
        if (id == null) {
            return null;
        }
        return this.actionDaoImpl.getEntity(id);
    }

    @Transactional
    public DataQuery createActionSimpleQuery(DataQuery query) {
        DataQuery dbQuery =
                DataQuery.init(query, "ALONE_AUTH_ACTION",
                        "ID,LOGINIS,CHECKIS,STATE,MUSER,CUSER,UTIME,CTIME,COMMENTS,NAME,AUTHKEY");
        return dbQuery;
    }

    @Transactional
    public Actiontree insertActiontreeEntity(Actiontree entity, LoginUser user, String authkey) {
        entity.setCuser(user.getId());
        entity.setCtime(TimeTool.getTimeDate14());
        entity.setUuser(user.getId());
        entity.setUtime(TimeTool.getTimeDate14());
        entity.setState("1");
        if (entity.getParentid() == null) {
            entity.setParentid("NONE");
        }

        if (entity.getType().equals("1")) {
            entity.setActionid(null);
        } else if ((entity.getActionid() == null) ||
                (entity.getActionid().trim().length() <= 0)) {
            Action action = new Action();
            action.setAuthkey(authkey);
            String actionName = "";
            if (!entity.getParentid().equals("NONE"))
                actionName = this.actiontreeDaoImpl.getEntity(
                        entity.getParentid()).getName() +
                        '_' + entity.getName();
            else {
                actionName = entity.getName();
            }
            action.setName(actionName);
            action.setCheckis("1");
            action.setLoginis("1");
            action.setState("1");
            entity.setActionid(insertActionEntity(action, user).getId());
        }

        entity.setTreecode("NONE");
        entity = this.actiontreeDaoImpl.insertEntity(entity);
        initTreeCode(entity.getId());
        return entity;
    }

    @Transactional
    public Actiontree editActiontreeEntity(Actiontree entity, LoginUser user, String authkey) {
        Actiontree entity2 = this.actiontreeDaoImpl.getEntity(entity.getId());
        entity2.setUuser(user.getId());
        entity2.setUtime(TimeTool.getTimeDate14());
        entity2.setParams(entity.getParams());
        entity2.setImgid(entity.getImgid());
        entity2.setIcon(entity.getIcon());
        entity2.setActionid(entity.getActionid());
        entity2.setState(entity.getState());
        entity2.setType(entity.getType());
        entity2.setComments(entity.getComments());
        entity2.setName(entity.getName());
        entity2.setSort(entity.getSort());

        if (entity.getType().equals("1")) {
            entity.setActionid(null);
        } else if ((entity.getActionid() == null) ||
                (entity.getActionid().trim().length() <= 0)) {
            Action action = new Action();
            action.setAuthkey(authkey);
            String actionName = "";
            if (!entity.getParentid().equals("NONE"))
                actionName = this.actiontreeDaoImpl.getEntity(
                        entity.getParentid()).getName() +
                        '_' + entity.getName();
            else {
                actionName = entity.getName();
            }
            action.setName(actionName);
            action.setCheckis("1");
            action.setLoginis("1");
            entity.setActionid(insertActionEntity(action, user).getId());
        }

        this.actiontreeDaoImpl.editEntity(entity2);
        return entity2;
    }

    @Transactional
    public void deleteActiontreeEntity(String id, LoginUser user) {
        if (this.actiontreeDaoImpl.selectEntitys(
                DBRule.addRule(new ArrayList(), "parentid", id, "="))
                .size() > 0) {
            throw new RuntimeException("不能删除该节点，请先删除其子节点");
        }
        this.actiontreeDaoImpl.deleteEntity(this.actiontreeDaoImpl.getEntity(id));
    }

    @Transactional
    public Actiontree getActiontreeEntity(String id) {
        if (id == null) {
            return null;
        }
        return this.actiontreeDaoImpl.getEntity(id);
    }

    @Transactional
    public DataQuery createActiontreeSimpleQuery(DataQuery query) {
        DataQuery dbQuery =
                DataQuery.init(query,
                        "ALONE_AUTH_ACTIONTREE",
                        "ID,PARAMS,IMGID,ICON,DOMAIN,ACTIONID,STATE,UUSER,CUSER,UTIME,CTIME,TYPE,COMMENTS,TREECODE,NAME,PARENTID,SORT");
        return dbQuery;
    }

    @Transactional
    public List<EasyUiTreeNode> getSyncTree(String parentId, String domain) {
        if (parentId == null) {
            parentId = "NONE";
        }
        if (domain == null) {
            domain = "alone";
        }
        return
                EasyUiTreeNode.formatAsyncAjaxTree(
                        EasyUiTreeNode.queryTreeNodeOne(
                                parentId,
                                "SORT",
                                "(SELECT c.NAME AS NAME,SORT,c.ID AS ID,PARENTID,ICON,b.AUTHKEY as URL,c.PARAMS as PARAM,domain FROM alone_auth_actiontree c LEFT JOIN alone_auth_action b ON c.ACTIONID=b.ID)",
                                "ID", "PARENTID", "NAME", "ICON",
                                "and a.DOMAIN='" + domain + "'",
                                "URL,PARAM").getResultList(),
                        EasyUiTreeNode.queryTreeNodeTow(parentId, "SORT",
                                "alone_auth_actiontree", "ID",
                                "PARENTID", "NAME", "ICON",
                                "and a.DOMAIN='" + domain + "'")
                                .getResultList(), "PARENTID", "ID", "NAME",
                        "ICON");
    }

    @Transactional
    public void moveActionTreeNode(String treeNodeId, String targetTreeNodeId) {
        Actiontree node = getActiontreeEntity(treeNodeId);
        if (node.getParentid().equals("NONE")) {
            throw new RuntimeException("不能够移动根节点!");
        }
        Actiontree target = getActiontreeEntity(targetTreeNodeId);
        if (target.getTreecode().indexOf(node.getTreecode()) >= 0) {
            throw new RuntimeException("不能够移动到其子节点下!");
        }
        node.setParentid(targetTreeNodeId);
        this.actiontreeDaoImpl.editEntity(node);

        List<Actiontree> list = this.actiontreeDaoImpl.getAllSubNodes(treeNodeId);
        for (Actiontree action : list) {
            action.setDomain(target.getDomain());
            this.actiontreeDaoImpl.editEntity(action);
            initTreeCode(action.getId());
        }
    }

    private void initTreeCode(String treeNodeId) {
        Actiontree node = getActiontreeEntity(treeNodeId);
        if (node.getParentid().equals("NONE"))
            node.setTreecode(node.getId());
        else {
            node.setTreecode(this.actiontreeDaoImpl.getEntity(node.getParentid())
                    .getTreecode() + node.getId());
        }
        this.actiontreeDaoImpl.editEntity(node);
    }

    @Transactional
    public AuthKey getCacheAction(String key) {
        if (this.keyMap.size() <= 0) {
            List<Action> list = this.actionDaoImpl.getAllEntity();
            for (Action node : list) {
                AuthKeyImpl authkey = new AuthKeyImpl();
                authkey.setIscheck(node.getCheckis().equals("1"));
                authkey.setIslogin(node.getLoginis().equals("1"));
                authkey.setUseAble(node.getState().equals("1"));
                authkey.setTitle(node.getName());
                this.keyMap.put(node.getAuthkey(), authkey);
            }
        }
        return (AuthKey) this.keyMap.get(key);
    }

    @Transactional
    public List<WebMenu> getAllMenus() {
        DataQuery query =
                DataQuery.getInstance(
                        1,
                        "SORT,ID,PARENTID,NAME,TYPE,STATE,ICON,IMGID,PARAMS,AUTHKEY",
                        "(SELECT c.SORT,c.ID,c.PARENTID,c.NAME,c.TYPE,c.STATE,c.ICON,c.IMGID,c.PARAMS,d.AUTHKEY FROM  alone_auth_actiontree c LEFT JOIN alone_auth_action d ON d.ID=c.ACTIONID WHERE (d.STATE = '1' or d.STATE IS NULL) and c.type!='3' order by LENGTH(c.TREECODE),c.SORT asc) e");
        List menus = new ArrayList();
        query.setPagesize(1000);
        query.setNoCount();
        query.setDistinct(true);
        try {
            for (Map map : query.search().getResultList()) {
                AuthMenuImpl node = new AuthMenuImpl();
                node.setIcon(map.get("ICON") != null ? map.get("ICON")
                        .toString() : null);
                node.setId(map.get("ID") != null ? map.get("ID").toString() :
                        null);
                node.setName(map.get("NAME") != null ? map.get("NAME")
                        .toString() : null);
                node.setParams(map.get("PARAMS") != null ? map.get("PARAMS")
                        .toString() : null);
                node.setParentid(map.get("PARENTID") != null ? map.get(
                        "PARENTID").toString() : null);
                node.setUrl(map.get("AUTHKEY") != null ? map.get("AUTHKEY")
                        .toString() : null);
                menus.add(node);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return menus;
    }

    @Transactional
    public List<Action> getAllActions() {
        DataQuery dbQuery = DataQuery.getInstance(1,
                "d.id,d.AUTHKEY,d.NAME,d.COMMENTS,d.STATE,d.CHECKIS,d.LOGINIS",
                " alone_auth_action d ");
        dbQuery.addRule(new DBRule("d.STATE", "1", "="));
        dbQuery.setDistinct(true);
        dbQuery.setNoCount();
        dbQuery.setPagesize(5000);
        List<Action> list = new ArrayList();
        try {
            for (Map node : dbQuery.search().getResultList()) {
                Action action = new Action();
                action.setAuthkey(node.get("D_AUTHKEY") != null ? node.get(
                        "D_AUTHKEY").toString() : null);
                action.setId(node.get("D_ID") != null ? node.get("D_ID")
                        .toString() : null);
                action.setName(node.get("D_NAME") != null ? node.get("D_NAME")
                        .toString() : null);
                action.setComments(node.get("D_COMMENTS") != null ? node.get(
                        "D_COMMENTS").toString() : null);
                action.setState(node.get("D_STATE") != null ? node.get(
                        "D_STATE").toString() : null);
                action.setCheckis(node.get("D_CHECKIS") != null ? node.get(
                        "D_CHECKIS").toString() : null);
                action.setLoginis(node.get("D_LOGINIS") != null ? node.get(
                        "D_LOGINIS").toString() : null);
                list.add(action);
            }
        } catch (SQLException e) {
            throw new RuntimeException();
        }
        return list;
    }

    public ActionDaoInter getActionDaoImpl() {
        return this.actionDaoImpl;
    }

    public void setActionDaoImpl(ActionDaoInter actionDaoImpl) {
        this.actionDaoImpl = actionDaoImpl;
    }

    public ActiontreeDaoInter getActiontreeDaoImpl() {
        return this.actiontreeDaoImpl;
    }

    public void setActiontreeDaoImpl(ActiontreeDaoInter actiontreeDaoImpl) {
        this.actiontreeDaoImpl = actiontreeDaoImpl;
    }
}